home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
turboinc.arc
/
FILESYS.INC
next >
Wrap
Text File
|
1985-09-25
|
21KB
|
735 lines
procedure filesys;
const
mostfiles = 40;
soh = 1;
eot = 4;
ack = 6;
nak = $15;
can = $18;
C = $43;
drivecap = 191; {Kbyte capacity of files drive}
ksize = 1; {minimum increment of file size in Kbytes}
type
filerec = record
title: name;
submit: integer;
date: name;
size: integer;
accesses: integer;
ASCII: boolean;
section: byte;
public: boolean;
end;
channel = array[0..127] of byte;
var
filefile: file of filerec;
filetab: array[0..mostfiles] of filerec;
filebuff: array [0..16] of channel;
datafile: file;
chksum: byte;
CRC: integer;
crcmode: boolean;
enddir: integer;
comch: char;
procedure xmit(x:byte);
begin
xmitchar(chr(x));
end;
function inbyte: byte;
var temp: char;
begin
repeat until inready or not cts;
if keypressed then read(kbd, temp) else temp := recvchar;
inbyte := ord(temp);
end;
procedure calcCRC(data:byte);
var
carry: boolean;
i: byte;
begin
chksum := lo(chksum + data);
for i := 0 to 7 do begin
carry := (crc and $8000) <> 0;
crc := crc shl 1;
if (data and $80) <> 0 then crc := crc or $0001;
if carry then crc := crc xor $1021;
data := lo(data shl 1);
end;
end;
procedure sendcalc(ch : byte);
begin
xmit(ch);
calcCRC(ch);
end;
procedure acknak(var inch: byte; time: integer);
var loop, loopend: integer;
begin
loopend := 100 * time;
loop := 0;
inch := 0;
repeat
delay(10);
if inready then inch := inbyte;
loop :=loop + 1;
until (inch in [ack, nak, can, C]) or (loop >= loopend) or not cts;
end;
function acknakout(ch : byte): boolean;
var times, loops: integer;
begin
times := 0;
repeat
loops := 0;
xmit(ch);
while (loops < 10) and not timedin do loops := loops + 1;
times := times + 1;
until inready or (times > 9) or not cts;
acknakout := inready and cts;
end;
procedure download(var successful: boolean);
var
inch, loop: byte;
blocknum, period, tries: integer;
done: boolean;
temp: line;
begin
reset(datafile);
str(filesize(datafile):4, temp);
lineout('Ready for XMODEM transfer:');
lineout('File open:' + temp + ' records;');
lineout('To cancel: type CTL-X until you return to command prompt.');
blockread(datafile, filebuff[0], 1);
done := false;
tries := 0;
blocknum := 1;
crcmode := false;
repeat
acknak(inch, 60);
if inch = 0 then inch := can;
if inch = C then begin
crcmode := true;
writeln('CRC mode requested');
end;
if inch = ack then begin
if eof(datafile) then done := true else begin
write(cr + 'Sent #', blocknum:4);
blockread(datafile, filebuff[0], 1);
blocknum := blocknum + 1;
tries := 0;
end;
end
else tries := tries + 1;
if (inch <> can) and cts and not done then begin
xmit(soh);
xmit(lo(blocknum));
xmit(255-lo(blocknum));
chksum := 0;
crc := 0;
for loop := 0 to 127 do sendcalc(filebuff[0][loop]);
calcCRC(0);
calcCRC(0);
if crcmode then begin xmit(hi(crc)); xmit(lo(crc)); end
else xmit(chksum);
end;
if tries = 5 then crcmode := not crcmode;
until (inch = can) or done or (tries= 10) or not cts;
successful := done;
tries := 0;
if successful and cts then repeat
xmit(eot);
acknak(inch, 10);
tries := tries + 1;
until (inch=ack) or (tries > 10) or not cts;
if cts and (inch <> can) and not successful then xmit(can);
close(datafile);
end;
function recchar(var error: boolean): byte;
var temp: byte;
begin
temp := 0;
if not cts then error := true;
if not error then begin
if not timedin then error := true
else begin
temp := inbyte;
calcCRC(temp);
recchar := temp;
end;
end;
end;
procedure clearline;
var junk: byte;
begin
while timedin do junk := inbyte;
end;
{$I-}
procedure upload(var successful: boolean);
var
blocknum, tries, byteloc : integer;
comp, locblock, crc2 : integer;
fatal, error, done : boolean;
opening, inch, locrc : byte;
hicrc, csum2, mode : byte;
begin
lineout('Beginning XMODEM protocol upload:');
lineout('To cancel: type CTRL-X until you return to command prompt.');
tries := 0;
done := false;
opening := 0;
locblock := 1;
rewrite(datafile);
fatal := ioresult > 0;
if crcmode then mode := C else mode := nak;
if cts and not fatal then fatal := not acknakout(mode);
while cts and not (done or fatal) do begin
tries := tries + 1;
error := false;
opening := recchar(error);
if opening = can then fatal := true;
if opening = eot then done := true;
if (opening <> eot) and (opening <> soh) and not fatal
then error := true;
if cts and not (error or fatal or done) then begin
blocknum := recchar(error);
comp := recchar(error);
if lo(comp + blocknum + opening) <> 0 then error := true;
byteloc := 0;
crc := 0;
chksum := 0;
while (byteloc < 128) and not (error or fatal) do begin
filebuff[0][byteloc] := recchar(error);
byteloc := byteloc + 1;
end;
if cts and not (error or fatal) then begin
calcCRC(0);
calcCRC(0);
crc2 := crc;
csum2 := chksum;
hicrc := recchar(error);
if crcmode then begin
locrc := recchar(error);
if (lo(crc2) <> locrc) or (hi(crc2) <> hicrc) then error := true;
end else if csum2 <> hicrc then error := true;
if (lo(locblock) <> blocknum)
and (lo(locblock) <> lo(blocknum+1))
and not error
then fatal := true;
if (lo(locblock) = blocknum) and not (error or fatal) then begin
blockwrite(datafile, filebuff[0], 1);
write(cr + ' Received #', blocknum:4);
if IOresult <> 0 then fatal := true;
tries := 0;
locblock := locblock + 1;
end;
end;
end;
if not (fatal or error) then flush else clearline;
if done or not (error or fatal) then fatal := not acknakout(ack);
if error and not fatal then begin
fatal := not acknakout(nak);
if tries > 6 then crcmode := not crcmode;
end;
end;
if fatal then xmit(can);
if done then xmit(ack);
close(datafile);
successful := (IOresult = 0) and done and not fatal;
if not successful then erase(datafile);
end;
procedure storebuff(var buffernum: byte; var paused, aborted: boolean);
var loop: byte;
begin
loop := 0;
while (loop < buffernum) and not aborted do begin
blockwrite(datafile, filebuff[loop], 1);
if IOresult > 0 then aborted := true;
loop := loop + 1;
end;
if buffernum in [1..16] then filebuff[0] := filebuff[buffernum];
buffernum := 0;
repeat xmit(17) until timedin;
paused := false;
end;
procedure textcap(var successful: boolean);
var
buffernum, where, loop : byte;
cc, cz, paused : boolean;
withecho, done, aborted : boolean;
temp : byte;
begin
withecho := (getcap('Do you want your text echoed (Y/N) ? ') = 'Y');
lineout('Beginning text capture: two CTRL-Cs abort, two CTRL-Zs end.');
cc := false;
cz := false;
done := false;
paused := false;
buffernum := 0;
where := 0;
rewrite(datafile);
aborted := (IOresult > 0);
while cts and not (done or aborted) do begin
if paused then
if not timedin then storebuff(buffernum, paused, aborted);
temp := inbyte;
if not cts then aborted := true;
if withecho and outready then xmit(temp);
if temp = 3 then begin if cc then aborted := true else cc := true; end
else cc := false;
if temp = 26 then begin if cz then done := true else cz := true; end
else cz := false;
filebuff[buffernum][where] := temp;
where := where + 1;
if where > 127 then begin
where := 0;
buffernum := buffernum + 1;
end;
if buffernum > 14 then begin
xmit(19);
paused := true;
end;
if buffernum > 16 then aborted := true;
end;
if done and cts and not aborted then begin
buffernum := buffernum + 1;
storebuff(buffernum, paused, aborted);
end;
close(datafile);
if aborted and (IOresult = 0) then erase(datafile);
successful := done and (IOresult=0) and not aborted;
end;
{$I+}
function exists(filename: name): boolean;
var found: boolean;
begin
assign(datafile, filename);
{$I-} reset(datafile) {$I+};
found := (IOresult = 0);
if found then close(datafile);
exists := found;
end;
function alpha(filename: name): boolean;
var strpos: integer;
okay: boolean;
dots: byte;
begin
dots := 0;
alpha := true;
if length(filename) > 0 then
for strpos := 1 to length(filename) do begin
if filename[strpos] = '.' then dots := dots + 1;
if not (filename[strpos] in ['.', '-', '_', '0'..'9', 'A'..'Z'])
then alpha := false;
end;
if dots > 1 then alpha := false;
end;
function getlegal: name;
var filename: name;
dotpos: integer;
begin
repeat
filename := allcaps(getinput('Enter name of file ? ', 12, echo));
dotpos := pos('.', filename);
until ((dotpos < 10) and (dotpos <> 1)
and (not((dotpos = 0) and (length(filename) > 8)))
and (not((dotpos > 0) and (length(filename) > dotpos + 3)))
and alpha(filename))
or (filename = '');
getlegal := filename;
end;
function dirpos(filename: name): integer;
var loopvar: integer;
begin
dirpos := 0;
loopvar := 0;
repeat
loopvar := loopvar + 1;
until (filetab[loopvar].title = filename) or (loopvar >= enddir);
if filetab[loopvar].title = filename then dirpos := loopvar;
end;
function getsect: byte;
var temp: integer;
begin
if sectsin then repeat
temp := getint(numsects, 0, 'Which section (0 for all, ? for list) ? ');
if temp = -1 then listsections else getsect := temp;
until (temp <> -1) or not cts
else getsect := 1;
end;
procedure addfile(filename: name; sectnum: byte; xmodem: boolean);
begin
with filetab[enddir + 1] do begin
title := filename;
submit := usernum;
if clockin then date := timeon;
assign(datafile, filedrive + filename);
reset(datafile);
size := filesize(datafile);
close(datafile);
accesses := 0;
ASCII := not xmodem;
section := sectnum;
public := false;
end;
end;
procedure newfile(xmodem: boolean);
var
filename: name;
successful: boolean;
sectnum: byte;
begin
clearsc;
if enddir >= mostfiles then lineout('No file space available.')
else begin
stringout('Upload: ');
filename := getlegal;
if filename <> '' then begin
if exists(filedrive + filename) then lineout('File name in use.')
else begin
repeat sectnum := getsect until (sectnum <> 0) or not cts;
assign(datafile, filedrive + filename);
if cts then begin
if xmodem then upload(successful)
else textcap(successful);
if successful then addfile(filename, sectnum, xmodem);
clearline;
if successful then enddir := enddir + 1
else lineout('Fatal transfer error or disk full...');
end;
end;
end;
end;
end;
function legaltab(prompt: line): integer;
var filename: name;
tabloc: integer;
begin
tabloc := 0;
clearsc;
stringout(prompt);
filename := getlegal;
if filename <> '' then begin
tabloc := dirpos(filename);
if tabloc <> 0 then
if not (filetab[tabloc].public or (access > reg)) then tabloc := 0;
if tabloc <> 0 then assign(datafile, filedrive + filename)
else if filename <> '' then lineout('No such file available.');
end;
legaltab := tabloc;
end;
procedure transmitfile;
var
successful: boolean;
tabloc: integer;
begin
tabloc := legaltab('Download: ');
if tabloc > 0 then begin
download(successful);
if successful then with filetab[tabloc] do
accesses := accesses + 1
else lineout('Transfer failed.');
end;
end;
procedure textdump;
var
tabloc : integer;
libname: longname;
begin
tabloc := legaltab('ASCII text dump: ');
lineout(space);
if tabloc > 0 then with filetab[tabloc] do begin
libname := title;
if copy(title, pos('.', title), 4) = '.LBR' then begin
lineout(title + ' is a library file: please select a member: ');
libname := getlegal;
if libname = '' then libname := 'DIR';
libname := copy(title, 1, length(title)-4) + '/' + libname;
end;
typefile(filedrive + libname, false);
if not cancelled then accesses := accesses + 1;
end;
end;
procedure showspace;
var loop, howbig, howmuch, sectmin : integer;
temp : line;
begin
sectmin := ksize shl 3;
howmuch := drivecap;
if enddir > 0 then for loop := 1 to enddir do
with filetab[loop] do begin
howbig := (size + sectmin - 1) div sectmin;
howmuch := howmuch - howbig;
end;
str(howmuch:4, temp);
if cts then lineout(cr + lf + temp + 'K space remaining.');
end;
procedure dir(sectnum: byte);
var loop, spaces : byte;
howbig, sectmin : integer;
any : boolean;
temp : line;
begin
any := false;
sectmin := ksize shl 3;
lineout(space);
if sectsin then lineout('Section ' + sect[sectnum] + ':');
if enddir > 0 then for loop := 1 to enddir do with filetab[loop] do begin
howbig := (size + sectmin - 1) div sectmin;
if cts and (public or (access = sysop) or (submit = usernum))
and (sectnum = section) then begin
str(howbig:4, temp);
for spaces := length(title) to 13 do temp := ' ' + temp;
stringout(title + temp + 'K');
if clockin then stringout(' ' + date);
if not public then stringout(' * Private *');
lineout(space);
if (access = sysop) or (submit = usernum) then begin
str(accesses:4, temp);
lineout('Accesses: ' + temp + ' From: ' + getname(submit));
end;
any := true;
end;
end;
if cts and not any then lineout('No files found.');
end;
procedure directory;
var sectnum : byte;
begin
stringout('Directory: ');
sectnum := getsect;
if sectnum > 0 then dir(sectnum)
else for sectnum := 1 to numsects do dir(sectnum);
showspace;
end;
procedure ldir;
var
tabloc : integer;
begin
tabloc := legaltab('Library directory: ');
lineout(space);
if tabloc > 0 then typefile(filedrive + filetab[tabloc].title + '/DIR', false);
end;
procedure killfile;
var loop, tabloc: integer;
begin
tabloc := legaltab('Delete: ');
if tabloc > 0 then begin
erase(datafile);
if enddir > tabloc then for loop := tabloc + 1 to enddir do
filetab[loop - 1] := filetab[loop];
enddir := enddir - 1;
end;
end;
procedure installfile;
var filename : name;
sectnum : byte;
begin
if enddir < mostfiles then begin
filename := getlegal;
if filename <> '' then begin
if exists(filedrive+filename) and (dirpos(filename) = 0) then begin
repeat sectnum := getsect until (sectnum <> 0) or not cts;
addfile(filename, sectnum, true);
enddir := enddir + 1;
lineout('File installed.');
end;
end;
end;
end;
function newname(tabloc: integer): name;
var filename: name;
begin
newname := filetab[tabloc].title;
stringout('New name? ');
filename := getlegal;
if (filename <> '') then begin
if not exists(filedrive + filename) then begin
assign(datafile, filedrive + filetab[tabloc].title);
rename(datafile, filename);
newname := filename;
stringout('File renamed.');
end
else lineout('Name in use - cannot rename.');
end;
end;
procedure editheader;
var tabloc: integer;
filename: name;
innum: integer;
sectstring: name;
begin
tabloc := legaltab('Edit: ');
if tabloc > 0 then with filetab[tabloc] do begin
repeat
str(section:3, sectstring);
lineout(space);
lineout('1- Name : ' + title);
lineout('2- From : ' + getname(submit));
lineout('3- Section : ' + sectstring);
lineout('4- Public? : ' + yn[public]);
lineout(space);
innum := getint(4, 0, 'Number of parameter to change? ');
case innum of
1: title := newname(tabloc);
2: submit := getid('Name of submitter? ');
3: repeat section := getsect until (section <> 0) or not cts;
4: public := not public;
end;
until (innum = 0) or not cts;
assign(datafile, filedrive + title);
reset(datafile);
size := filesize(datafile);
close(datafile);
end else lineout('File not in directory.');
end;
procedure initfile;
var
loopvar: integer;
temp: name;
begin
lineout('Initializing file system...');
loopvar := 0;
assign(filefile, 'FILES.BBS');
{$I-} reset(filefile) {$I+};
if IOresult = 0 then begin
while not eof(filefile) do begin
loopvar := loopvar + 1;
read(filefile, filetab[loopvar]);
end;
close(filefile);
end;
enddir := loopvar;
filesopen := true;
end;
procedure closefile;
var loopvar: integer;
begin
rewrite(filefile);
if enddir > 0 then
for loopvar := 1 to enddir do write(filefile, filetab[loopvar]);
close(filefile);
filesopen := false;
end;
begin
clearsc;
initfile;
if not expert then outfile(filemenu);
repeat
lineout(space);
comch := getcap('Files command (or ? for menu) ? ');
case comch of
'D' : directory;
'S' : transmitfile;
'T' : textdump;
'H' : outfile(filehelp);
'G' : disconnect;
'?' : outfile(filemenu);
'L' : ldir;
'U' : if access>newuser then begin crcmode := true; newfile(true); end;
'C' : if access>newuser then begin crcmode := false; newfile(true); end;
'V' : if access>newuser then newfile(false);
'K' : if access = sysop then killfile;
'I' : if access = sysop then installfile;
'E' : if access = sysop then editheader;
end;
until (comch = 'Q') or not cts;
if cts then lineout('Closing file system...');
closefile;
end;